/**                                                                                                                                                                                
 * Copyright (c) 2010 Yahoo! Inc. All rights reserved.                                                                                                                             
 *                                                                                                                                                                                 
 * Licensed under the Apache License, Version 2.0 (the "License"); you                                                                                                             
 * may not use this file except in compliance with the License. You                                                                                                                
 * may obtain a copy of the License at                                                                                                                                             
 *                                                                                                                                                                                 
 * http://www.apache.org/licenses/LICENSE-2.0                                                                                                                                      
 *                                                                                                                                                                                 
 * Unless required by applicable law or agreed to in writing, software                                                                                                             
 * distributed under the License is distributed on an "AS IS" BASIS,                                                                                                               
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or                                                                                                                 
 * implied. See the License for the specific language governing                                                                                                                    
 * permissions and limitations under the License. See accompanying                                                                                                                 
 * LICENSE file.                                                                                                                                                                   
 */

package tlsb;

import generator.CounterGenerator;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import util.Configuration;
import util.IFileReader;
import util.TextFileLoader;

/**
 * Utility functions.
 */
public class Utils {
	static Random random = new Random();
	static CounterGenerator llsequence = new CounterGenerator(0);
	static LinkedList<LinkedList<String>> lll = new LinkedList<LinkedList<String>>();

	/**
	 * Generate a random ASCII string of a given length.
	 */
	public static String ASCIIString(int length) {
		int interval = '~' - ' ' + 1;

		byte[] buf = new byte[length];
		random.nextBytes(buf);
		for (int i = 0; i < length; i++) {
			if (buf[i] < 0) {
				buf[i] = (byte) ((-buf[i] % interval) + ' ');
			} else {
				buf[i] = (byte) ((buf[i] % interval) + ' ');
			}
		}
		return new String(buf);
	}

	/**
	 * Hash an integer value.
	 */
	public static int hash(int val) {
		return FNVhash32(val);
	}

	public static final int FNV_offset_basis_32 = 0x811c9dc5;
	public static final int FNV_prime_32 = 16777619;

	/**
	 * 32 bit FNV hash. Produces more "random" hashes than (say)
	 * String.hashCode().
	 * 
	 * @param val
	 *            The value to hash.
	 * @return The hash value
	 */
	public static int FNVhash32(int val) {
		// from http://en.wikipedia.org/wiki/Fowler_Noll_Vo_hash
		int hashval = FNV_offset_basis_32;

		for (int i = 0; i < 4; i++) {
			int octet = val & 0x00ff;
			val = val >> 8;

			hashval = hashval ^ octet;
			hashval = hashval * FNV_prime_32;
			// hashval = hashval ^ octet;
		}
		return Math.abs(hashval);
	}

	public static final long FNV_offset_basis_64 = 0xCBF29CE484222325L;
	public static final long FNV_prime_64 = 1099511628211L;

	/**
	 * 64 bit FNV hash. Produces more "random" hashes than (say)
	 * String.hashCode().
	 * 
	 * @param val
	 *            The value to hash.
	 * @return The hash value
	 */
	public static long FNVhash64(long val) {
		// from http://en.wikipedia.org/wiki/Fowler_Noll_Vo_hash
		long hashval = FNV_offset_basis_64;

		for (int i = 0; i < 8; i++) {
			long octet = val & 0x00ff;
			val = val >> 8;

			hashval = hashval ^ octet;
			hashval = hashval * FNV_prime_64;
			// hashval = hashval ^ octet;
		}
		return Math.abs(hashval);
	}

	public static String joinStr(String str1, String str2) {
		String result = "";
		StringBuilder sb = new StringBuilder();
		sb.append(str1);
		sb.append(str2);
		result = sb.toString();
		sb.delete(0, sb.length());
		return result;
	}

/*	private static Queue<String> statusQueue = new ConcurrentLinkedQueue<String>();
	private static final int QUEUE_LOWER = 50000;
	private static boolean eof = false;
	private static boolean loading = true;
	private static Lock lock = new ReentrantLock();
	private static Condition startCond = lock.newCondition();*/
	static TextFileLoader statusLoader = new TextFileLoader(Configuration.instance()
			.getStatusFile(), Configuration.instance().getStatusFileCount(), Configuration.instance().getQueueThreshold());

	// private static final String statusFile =
	// "/home/xiafan/weibo/fortest/status/part-0000";
	static AtomicLong mid = new AtomicLong(0);
	public static void init() {
		statusLoader.start();
	}

	public static void loadMap() {
		IFileReader ifr = new IFileReader(new File("n.txt"));
		ifr.open();
		String line = null;
		// fstc 1873806460 6803394
		// cfs1449397358 6803394
		while ((line = ifr.readLine()) != null) {
			if (line.startsWith("fstc")) {
				String[] fields = line.split("\t");
				cidUidMap.put(fields[1], fields[2]);
			} else {
				String[] fields = line.split("\t");
				cidSidMap.put(fields[0].substring(3), fields[1]);
			}
		}
		ifr.close();
	}

	private static Map<String, String> cidUidMap = new HashMap<String, String>();

	public static String getCidOfUid(String uid) {
		return cidUidMap.get(uid);
	}

	private static Map<String, String> cidSidMap = new HashMap<String, String>();

	public static String getCidOfSid(String sid) {
		return cidSidMap.get(sid);
	}

	public static void cleanup() {
		statusLoader.close();
	}

	public static String getCurList() {
		String ret = statusLoader.readLine();
		if (ret != null) {
			String[] fields = ret.split("\t");
			ret = String.format("%d\t%s", mid.incrementAndGet(), fields[1]);
		}
		/*while (!eof) {
			ret = statusQueue.poll();
			if (ret != null) {
				if (statusQueue.size() < QUEUE_LOWER / 2 && loading == false) {
					try {
						lock.lock();
						startCond.signal();
					} finally {
						lock.unlock();
					}
				}
				break;
			}
		}*/
		return ret;
	}

	/*
	 * public static ConcurrentHashMap<Integer, String> getConcurrentHashMap(
	 * String filepath) { ConcurrentHashMap<Integer, String> chm = new
	 * ConcurrentHashMap<Integer, String>(); try { BufferedReader br = new
	 * BufferedReader(new FileReader(filepath)); String line = ""; int i = 0;
	 * while ((line = br.readLine()) != null) { chm.put(i++, line); if (i %
	 * 10000 == 0) { System.out.print("."); if (i % 100000 == 0)
	 * System.out.println(); } } br.close();
	 * 
	 * } catch (FileNotFoundException e) { e.printStackTrace(); System.exit(0);
	 * } catch (IOException e) { e.printStackTrace(); } return chm; }
	 */

}